`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    21:50:18 05/28/2015 
// Design Name: 
// Module Name:    ALU 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
// Alu para el trabajo MIPS - es solo un combinacional, 
// no guarda estado, asignaciones bloqueantes
// Instrucciones a implementar -> ver datasheet para ver que hacen
//
// TIPO R: SLL, SRL, SRA, SLLV, SRLV, SRAV, ADDU, SUBU 
//	AND, OR, XOR, NOR, SLT, SLTU
//
// TIPO I: LB, LH, LW, LWU, LBU, LHU, SB, SH, SW
//	ADDI, ADDIU, ANDI, ORI, XORI, LUI
//	SLTI, SLTIU, BEQ, BNE, J, JAL
//
// TIPO J : JR, JALR
//////////////////////////////////////////////////////////////////////////////////
module ALU #(parameter TAM_BUS = 32)(
	input [TAM_BUS-1:0] A, //RS
	input [TAM_BUS-1:0] B, // RT
	input [5:0] COD_OP,
	input [4:0] SA,	//Shift Amount
	output reg [TAM_BUS-1:0] C, //RD
	output wire Zero
 );
assign Zero = (C == 0); //Fijas si es 0
always @(A,B,COD_OP,SA) begin

	/****** Comunes ******/
	
	//Suma 100000
	if (COD_OP == 6'b 100000)
		 C = $signed(A) + $signed(B);
	//Resta 100010
	else if (COD_OP == 6'b 100010)
		 C = $signed(A) - $signed(B);
	//And 100100
	else if (COD_OP == 6'b 100100)
		 C = A & B;
	//Or 100101
	else if (COD_OP == 6'b 100101)
		 C = A | B;
	//Xor 100110
	else if (COD_OP == 6'b 100110)
		 C = A ^ B;
	//Nor 100111
	else if (COD_OP == 6'b 100111)
		 C = ~(A | B);
	
	/****** UNSIGNED ******/
	
	//Add Unsigned Word 100001
	else if (COD_OP == 6'b 100001)
		C = A + B;
	//Subtract Unsigned Word 100011		
	else if (COD_OP == 6'b 100011)
		C = A - B;
		
	/****** SHIFTS ******/
	
	//Shift Word Right Aritmetic 000011		
	else if (COD_OP == 6'b 000011)
		C = $signed(B) >>> SA;
	//Shift Word Right Logical	000010
	else if (COD_OP == 6'b 000010)
		C = B >> SA;
	//Shift Word Left Logical	000000
	else if (COD_OP == 6'b 000000)
		C = B << SA;
	//Shift Word Left Logical Variable 000100
	else if (COD_OP == 6'b 000100)
		C = B << A;
	//Shift Word Right Logical Variable	000110	
	else if (COD_OP == 6'b 000110)
		C = B >> A;
	//Shift Word Right Aritmetic Variable	000111
	else if (COD_OP == 6'b 000111)
		C = $signed(B) >>> A;
	
	
	/****** SETS ******/
	
	//Set On Less Than 101010
	else if (COD_OP == 6'b 101010) begin
		if($signed(A) < $signed(B)) C = 1;
		else C = 0;
	end
	//Set On Less Than Unsigned 101011	
	else if (COD_OP == 6'b 101011)
	begin
		if(A < B) C = 1;
		else C = 0;
	end
	
	/****** Ninguno ******/
	else C = 0;
	
end
endmodule
